package com.springboot.pratice.common.config.mthread;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

/**
 * @author zengjinliang
 * Create on 2021/12/7 16:35
 * 线程池管理实例
 */
@Slf4j
public class MThreadManager {

    public static Map<String,MThreadPoolExecutor> pools = Maps.newConcurrentMap();
    public static Map<String,String> fingerprints = Maps.newConcurrentMap();

    /**
     * 构建线程池对象
     * @param poolName 线程程名称
     * @param corePoolSize 核心线程数
     * @param maximumPoolSize 最大线程数
     * @param keepAliveTime 线程空闲时间(单位：毫秒)
     * @param allWaitSize 最大排队任务数
     */
    public static void create(String poolName,int corePoolSize,
                                        int maximumPoolSize,
                                        long keepAliveTime,int allWaitSize){
        if(!pools.containsKey(poolName)){
            MThreadPoolExecutor threadPoolExecutor= new MThreadPoolExecutor(poolName,corePoolSize,
                    maximumPoolSize, keepAliveTime, allWaitSize);
            pools.put(poolName,threadPoolExecutor);
            fingerprints.put(poolName,threadPoolExecutor.fingerprint());
            log.info("Initialize thread pool success. poolName="+poolName+", fingerprint=" + threadPoolExecutor.fingerprint());
        }else{
            log.warn("Initialize thread pool is exist. poolName=" + poolName);
        }
    }

    /**
     * 调整指定的线程池参数
     * @param poolName
     * @param corePoolSize
     * @param maximumPoolSize
     * @param keepAliveTime
     * @param allWaitSize
     * 触发线程池调整时，会比对之前的线程池参数特征，只有特征有变化时才会触发调整，如果一样则什么都不做
     */
    public static void adjust(String poolName,int corePoolSize,
                                        int maximumPoolSize,
                                        long keepAliveTime,int allWaitSize){

        if(pools.containsKey(poolName)){
            //通过调整参数计算特征，并对已有线程池进行对比
            String newTPfp = MThreadPoolExecutor.calFingerprint(poolName,corePoolSize,maximumPoolSize,
                    keepAliveTime,allWaitSize);
            String oldTPfp = fingerprints.get(poolName);
            if(!newTPfp.equals(oldTPfp)){
                //用新的线程池替掉原有线程池，并停掉之前的线程池
                MThreadPoolExecutor oTP = pools.get(poolName);
                pools.put(poolName,new MThreadPoolExecutor(poolName,corePoolSize,
                        maximumPoolSize, keepAliveTime, allWaitSize));
                fingerprints.put(poolName,newTPfp);
                oTP.shutdown();
            }else{
                log.info("Adjust thread pool fail.same fingerprint.poolName="+poolName+", fingerprint=" + oldTPfp);
            }
        }else{
            log.warn("Adjust thread pool error,TP non-existent. poolName=" + poolName);
        }

    }


    /**
     * 向指定的线程池提交任务
     * @param poolName
     * @param runnable
     */
    public static void submit(String poolName,Runnable runnable){
        if(pools.containsKey(poolName)){
            pools.get(poolName).submit(runnable);
        }else{
            throw new IllegalArgumentException("Runnable submit error,PoolThread not exist. poolName=" + poolName);
        }
    }

    public static void shutdown(String pname){
        if(pools.containsKey(pname)){
            pools.get(pname).shutdown();
        }
    }

    /**
     * 获取所有线程池状态
     * @return
     * [{"name":"pool1","corePoolSize":5,"maximumPoolSize":10,"activeCount":10,"taskQueue":5},{……}]
     */
    public static String monitor() {
        List status = Lists.newArrayList();
        for(MThreadPoolExecutor t:pools.values()){
            status.add(t.getState());
       }
        return null;
//       return JacksonTool.toJson(status);
    }
}
